package com.ruowei.modules.foodOrder.web.rest;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ruowei.common.error.exception.CommonException;
import com.ruowei.common.lang.StringUtils;
import com.ruowei.config.ApplicationProperties;
import com.ruowei.modules.foodOrder.domain.*;
import com.ruowei.modules.foodOrder.domain.enumeration.OrderStatus;
import com.ruowei.modules.foodOrder.pojo.dto.AppletMerchandiseListDTO;
import com.ruowei.modules.foodOrder.pojo.dto.MerchandiseDetailDTO;
import com.ruowei.modules.foodOrder.pojo.dto.MerchantDTO;
import com.ruowei.modules.foodOrder.pojo.dto.SkuPriceDTO;
import com.ruowei.modules.foodOrder.repository.*;
import com.ruowei.modules.foodOrder.service.LifeCycleService;
import com.ruowei.modules.foodOrder.service.MerchantService;
import com.ruowei.modules.foodOrder.service.PaymentFlowService;
import com.ruowei.modules.foodOrder.web.dto.*;
import com.ruowei.modules.sys.domain.SysUserRole;
import com.ruowei.modules.sys.domain.annotation.OrderLock;
import com.ruowei.modules.sys.domain.entity.QSysUser;
import com.ruowei.modules.sys.domain.enumeration.*;
import com.ruowei.modules.sys.domain.table.SysRole;
import com.ruowei.modules.sys.domain.table.SysUserTable;
import com.ruowei.modules.sys.repository.SysRoleRepository;
import com.ruowei.modules.sys.repository.SysUserRepository;
import com.ruowei.modules.sys.repository.SysUserRoleRepository;
import com.ruowei.modules.sys.service.OperateLogService;
import com.ruowei.modules.sys.utils.CommonUtils;
import com.ruowei.modules.webSocket.domain.enumeration.MessageType;
import com.ruowei.modules.webSocket.domain.enumeration.ReceiverType;
import com.ruowei.modules.webSocket.domain.enumeration.SenderType;
import com.ruowei.modules.webSocket.service.MessagePushService;
import com.ruowei.modules.wxpay.service.PayReturnService;
import com.ruowei.modules.wxpay.service.WeChatPayService;
import com.ruowei.security.CurrentUser;
import com.ruowei.security.UserModel;
import io.github.jhipster.web.util.PaginationUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import springfox.documentation.annotations.ApiIgnore;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * REST controller for managing {@link Merchant}.
 */
@RestController
@RequestMapping("/api")
@Transactional
@Api(tags = "商家信息")
public class MerchantResource {

    private final Logger log = LoggerFactory.getLogger(MerchantResource.class);

    private final ApplicationProperties applicationProperties;
    private final MerchantRepository merchantRepository;
    private final SysUserRepository sysUserRepository;
    private final PasswordEncoder passwordEncoder;
    private final SysRoleRepository sysRoleRepository;
    private final MerchandiseRepository merchandiseRepository;
    private final SysUserRoleRepository sysUserRoleRepository;
    private final OrderRepository orderRepository;
    private final MessagePushService messagePushService;
    private final LifeCycleService lifeCycleService;
    private final RefundApplicationRepository refundApplicationRepository;
    private final MerchantChangeLogRepository merchantChangeLogRepository;
    private final JPAQueryFactory queryFactory;
    private final MerchantService merchantService;
    private final WeChatPayService weChatPayService;
    private final PayReturnService payReturnService;
    private final PaymentFlowService paymentFlowService;
    private final OperateLogService operateLogService;

    private final QMerchant QM = QMerchant.merchant;
    private final QOrder qOrder = QOrder.order;
    private final QOrderItem qOrderItem = QOrderItem.orderItem;
    private final QSysUser qSysUser = QSysUser.sysUser;
    private final QCouriers qCouriers = QCouriers.couriers;

    public MerchantResource(ApplicationProperties applicationProperties, MerchantRepository merchantRepository, SysUserRepository sysUserRepository,
                            PasswordEncoder passwordEncoder, SysRoleRepository sysRoleRepository, MerchandiseRepository merchandiseRepository,
                            SysUserRoleRepository sysUserRoleRepository, OrderRepository orderRepository,
                            MessagePushService messagePushService, LifeCycleService lifeCycleService, RefundApplicationRepository refundApplicationRepository,
                            MerchantChangeLogRepository merchantChangeLogRepository, JPAQueryFactory queryFactory, MerchantService merchantService,
                            WeChatPayService weChatPayService, PayReturnService payReturnService, PaymentFlowService paymentFlowService, OperateLogService operateLogService) {
        this.applicationProperties = applicationProperties;
        this.merchantRepository = merchantRepository;
        this.sysUserRepository = sysUserRepository;
        this.passwordEncoder = passwordEncoder;
        this.sysRoleRepository = sysRoleRepository;
        this.merchandiseRepository = merchandiseRepository;
        this.sysUserRoleRepository = sysUserRoleRepository;
        this.orderRepository = orderRepository;
        this.messagePushService = messagePushService;
        this.lifeCycleService = lifeCycleService;
        this.refundApplicationRepository = refundApplicationRepository;
        this.merchantChangeLogRepository = merchantChangeLogRepository;
        this.queryFactory = queryFactory;
        this.merchantService = merchantService;
        this.weChatPayService = weChatPayService;
        this.payReturnService = payReturnService;
        this.paymentFlowService = paymentFlowService;
        this.operateLogService = operateLogService;
    }

    @GetMapping("/applet/merchant/getList")
    @ApiOperation(value = "获取商家列表")
    public ResponseEntity<List<MerchantDTO>> getList(@RequestParam(required = false) String merchantName) {
        List<MerchantDTO> list = merchantService.getList(merchantName);
        return ResponseEntity.ok(list);
    }

    @GetMapping("/applet/merchandiseList")
    @ApiOperation(value = "商家商品列表")
    public ResponseEntity<List<AppletMerchandiseListDTO>> merchandiseList(@RequestParam String merchandiseCode) {
        List<AppletMerchandiseListDTO> list = merchantService.merchandiseList(merchandiseCode);
        return ResponseEntity.ok(list);
    }

    @GetMapping("/applet/merchandise/detail")
    @ApiOperation(value = "获取商品详细-商品规格选项")
    public ResponseEntity<List<MerchandiseDetailDTO>> getMerchandiseDetail(@RequestParam String merchandiseCode) {
        List<MerchandiseDetailDTO> list = merchantService.getMerchandiseDetail(merchandiseCode);
        return ResponseEntity.ok(list);
    }

    @GetMapping("/applet/merchandise/getPriceBySku")
    @ApiOperation(value = "根据商品规格获取商品sku")
    public ResponseEntity<SkuPriceDTO> getPriceBySku(@RequestParam String optionCodes, @RequestParam String merchandiseCode) {
        SkuPriceDTO dto = merchantService.getPriceBySku(optionCodes, merchandiseCode);
        return ResponseEntity.ok(dto);
    }

    @PostMapping("/merchants")
    @ApiOperation(value = "新增商家-web")
    public ResponseEntity<Merchant> insertMerchant(@RequestBody AddMerchantDTO dto, @ApiIgnore @CurrentUser UserModel userModel) {
        if (merchantRepository.existsByPhoneAndStatusNot(dto.getPhone(), "删除")) {
            throw new CommonException("手机号已存在");
        }
        if (merchantRepository.existsByMerchantNameAndStatusNot(dto.getMerchantName(), "删除")) {
            throw new CommonException("商家名已存在");
        }
        Merchant merchant = new Merchant();
        String merchantCode = CommonUtils.getUUID();
        merchant.setMerchantCode(merchantCode);
        merchant.setMerchantName(dto.getMerchantName());
        merchant.setMerchantAddress(dto.getMerchantAddress());
        merchant.setPhone(dto.getPhone());
        merchant.setPhotos(dto.getPhotos());
        merchant.setDescription(dto.getDescription());
        merchant.setNotice(dto.getNotice());
        if (StringUtils.isEmpty(dto.getStatus())) {
            merchant.setStatus("停业");
        } else {
            merchant.setStatus(dto.getStatus());
        }
        merchant.setOpenTime(dto.getOpenTime());
        if (dto.getStartingPrice() != null) {
            merchant.setStartingPrice(dto.getStartingPrice());
        } else {
            merchant.setStartingPrice(new BigDecimal(0));
        }
//        merchant.setScore(new BigDecimal(0));
//        merchant.setFansNum(0L);
//        merchant.setCompositeScore(new BigDecimal(0));
//        merchant.setMerchandiseScore(new BigDecimal(0));
//        merchant.setServiceScore(new BigDecimal(0));
//        merchant.setDeliveryScore(new BigDecimal(0));
        merchant = merchantRepository.save(merchant);
        if (sysUserRepository.existsByUserCodeAndUserTypeAndStatus(merchantCode, UserType.COURIER, UserStatusType.NORMAL)) {
            throw new CommonException("不能重复添加");
        }
        if (sysUserRepository.existsByLoginCodeAndStatus(dto.getLoginCode(), UserStatusType.NORMAL)) {
            throw new CommonException("该账号已被使用");
        }
        SysUserTable sysUserTable = new SysUserTable();
        sysUserTable.setLoginCode(dto.getLoginCode());
        sysUserTable.setPhone(dto.getPhone());
        sysUserTable.setUserCode(merchantCode);
        sysUserTable.setUserName(merchant.getMerchantName());
        sysUserTable.setPassword(passwordEncoder.encode(dto.getPassword()));
        sysUserTable.setUserType(UserType.BUSINESS);
        sysUserTable.setStatus(UserStatusType.NORMAL);
        sysUserRepository.save(sysUserTable);
        Optional<SysRole> roleOptional = sysRoleRepository.getOneByRoleCode("ROLE_BUSINESS");
        SysRole sysRole;
        if (!roleOptional.isPresent()) {
            SysRole role = new SysRole();
            role.setIsSys(true);
            role.setRemarks("商家角色");
            role.setRoleCode("ROLE_BUSINESS");
            role.setRoleName("商家");
            role.setRoleType(RoleType.USER);
            role.setStatus(RoleStatusType.NORMAL);
            sysRole = sysRoleRepository.save(role);
        } else {
            sysRole = roleOptional.get();
        }
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setSysRoleId(sysRole.getId());
        sysUserRole.setSysUserId(sysUserTable.getId());
        sysUserRoleRepository.save(sysUserRole);
        //日志
        operateLogService.addLog(merchantCode, merchant.getMerchantName(), Merchant.class);

        return ResponseEntity.ok(merchant);
    }

    @PutMapping("/merchants/edit")
    @ApiOperation(value = "修改商家-web")
    public ResponseEntity<Merchant> alterMerchant(@RequestBody AlterMerchantDTO dto, @ApiIgnore @CurrentUser UserModel userModel) {
        Optional<Merchant> saler = merchantRepository.findByIdAndStatusNot(dto.getId(), "删除");
        if (!saler.isPresent()) {
            throw new CommonException("商家信息不存在");
        }
        if (merchantRepository.existsByMerchantNameAndStatusNotAndIdNot(dto.getMerchantName(), "删除", dto.getId())) {
            throw new CommonException("商家名已存在");
        }
        Merchant merchant = saler.get();
        if ("营业".equals(merchant.getStatus())) {
            throw new CommonException("商家正在营业中，请勿修改");
        }
        Merchant oldMerchant = SerializationUtils.clone(merchant);
        if (dto.getStartingPrice() != null) {
            merchant.setStartingPrice(dto.getStartingPrice());
        } else {
            merchant.setStartingPrice(new BigDecimal(0));
        }
        if (StringUtils.isNotEmpty(dto.getStatus())) {
            merchant.setStatus(dto.getStatus());
        } else {
            merchant.setStatus("营业");
        }
        merchant.setMerchantName(dto.getMerchantName());
        merchant.setMerchantAddress(dto.getMerchantAddress());
        merchant.setPhotos(dto.getPhotos());
        merchant.setPhone(dto.getPhone());
        merchant.setDescription(dto.getDescription());
        merchant.setNotice(dto.getNotice());
        merchant.setOpenTime(dto.getOpenTime());
        merchant = merchantRepository.saveAndFlush(merchant);
        //保存日志
        operateLogService.addUpdateLog(merchant.getMerchantCode(), merchant.getMerchantName(), oldMerchant, merchant);

        return ResponseEntity.ok(merchant);
    }


    @PostMapping("/merchantUpdatePassword/{id}")
    @ApiOperation(value = "商家修改账号密码接口")
    public ResponseEntity<Void> merchantUpdatePassword(@PathVariable Long id,
                                                       @RequestParam String password,
                                                       @RequestParam String loginCode,
                                                       @ApiIgnore @CurrentUser UserModel userModel) {
        Optional<Merchant> opt = merchantRepository.findByIdAndStatusNot(id, "删除");
        if (!opt.isPresent()) {
            throw new CommonException("商家不存在");
        }
        if ("营业".equals(opt.get().getStatus())) {
            throw new CommonException("商家正在营业中，请勿修改");
        }
        Optional<SysUserTable> sysUserOpt = sysUserRepository.findOneByUserCode(opt.get().getMerchantCode());
        if (!sysUserOpt.isPresent()) {
            throw new CommonException("账号异常");
        }
        if (sysUserRepository.existsByLoginCodeAndStatusAndIdNot(loginCode, UserStatusType.NORMAL, sysUserOpt.get().getId())) {
            throw new CommonException("该账号已被使用");
        }
        //密码最低6位，数字加字母组合，区分大小写
        if (Arrays.stream(password.split("")).filter(s -> !s.equals(" ")).count() < 6) {
            throw new CommonException("密码不得少于6位数");
        }
        for (char c : password.toCharArray()) {
            if (!Character.isDigit(c) && !Character.isLetter(c)) {
                throw new CommonException("密码只能为字母和数字组合");
            }
        }
        //账号为6-20位，数字加字母组合，区分大小写
        if (Arrays.stream(loginCode.split("")).filter(s -> !s.equals(" ")).count() < 6) {
            throw new CommonException("账号不得少于6位数");
        }
        if (Arrays.stream(loginCode.split("")).filter(s -> !s.equals(" ")).count() > 20) {
            throw new CommonException("账号不得大于20位数");
        }
        for (char c : loginCode.toCharArray()) {
            if (!Character.isDigit(c) && !Character.isLetter(c)) {
                throw new CommonException("账号只能为字母和数字组合");
            }
        }

        String Encoder = passwordEncoder.encode(password);
        SysUserTable sysUser = sysUserRepository.findOneByUserCode(opt.get().getMerchantCode()).orElseThrow(() -> new CommonException("账号不存在"));
        SysUserTable oldUser = SerializationUtils.clone(sysUser);
        sysUser.setLoginCode(loginCode);
        sysUser.setPassword(Encoder);
        sysUser = sysUserRepository.save(sysUser);
        //商家修改日志
        operateLogService.addUpdateLog(sysUser.getUserCode(), sysUser.getUserName(), oldUser, sysUser);

        return ResponseEntity.ok().build();
    }


    @PutMapping("/merchants/delete/{id}")
    @ApiOperation(value = "删除商家-web")
    public ResponseEntity<Void> deleteMerchant(@PathVariable Long id, @ApiIgnore @CurrentUser UserModel userModel) {
        if (id == null) {
            throw new CommonException("ID不能为空");
        }
        merchantRepository.findByIdAndStatusNot(id, "删除")
            .ifPresent(merchant -> {
                boolean exists = merchandiseRepository.existsByMerchantCodeAndDeleteStatus(merchant.getMerchantCode(), false);
                if (exists) {
                    throw new CommonException("商家存在商品信息，不能删除");
                }
                if ("营业".equals(merchant.getStatus())) {
                    throw new CommonException("商家营业中，不能删除");
                }
                queryFactory.update(qSysUser)
                    .set(qSysUser.status, UserStatusType.DELETE)
                    .where(qSysUser.userCode.eq(merchant.getMerchantCode()))
                    .execute();
                merchant.setStatus("删除");
                merchantRepository.save(merchant);
            });
        return ResponseEntity.ok().build();
    }

    @GetMapping("/merchants/detail/{id}")
    @ApiOperation(value = "商家详情-web")
    public ResponseEntity<MerchantsDTO> getMerchant(@PathVariable Long id, @ApiIgnore @CurrentUser UserModel userModel) {
        if (id == null) {
            throw new CommonException("ID不能为空");
        }
        Optional<Merchant> saler = merchantRepository.findByIdAndStatusNot(id, "删除");
        if (!saler.isPresent()) {
            throw new CommonException("商家信息不存在");
        }
        Merchant merchant = saler.get();
        Optional<SysUserTable> sysUserTable = sysUserRepository.findOneByUserCode(merchant.getMerchantCode());
        if (!sysUserTable.isPresent()) {
            throw new CommonException("账号信息不存在");
        }
        SysUserTable sysUser = sysUserTable.get();
        MerchantsDTO dto = new MerchantsDTO();
        dto.setLoginCode(sysUser.getLoginCode());
        dto.setMerchantCode(merchant.getMerchantCode());
        dto.setMerchantName(merchant.getMerchantName());
        dto.setMerchantAddress(merchant.getMerchantAddress());
        dto.setPhone(merchant.getPhone());
        dto.setPhotos(merchant.getPhotos());
        dto.setDescription(merchant.getDescription());
        dto.setNotice(merchant.getNotice());
        dto.setOpenTime(merchant.getOpenTime());
        dto.setStatus(merchant.getStatus());
        dto.setStartingPrice(merchant.getStartingPrice());
        dto.setProvince(merchant.getProvince());
        dto.setCity(merchant.getCity());
        dto.setDistrict(merchant.getDistrict());
        return ResponseEntity.ok(dto);
    }

    @GetMapping("/merchants/list")
    @ApiOperation(value = "商家列表-web")
    public ResponseEntity<Page<MerchantsDTO>> getMerchant(@RequestParam(required = false) String merchantName,
                                                          @ApiIgnore @CurrentUser UserModel userModel,
                                                          Pageable pageable) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QM.status.ne("删除"));
        if (StringUtils.isNotEmpty(merchantName)) {
            booleanBuilder.and(QM.merchantName.contains(merchantName));
        }
        JPAQuery<MerchantsDTO> jpaQuery = queryFactory.select(Projections.bean(MerchantsDTO.class, QM.id, QM.merchantCode, QM.merchantName, QM.phone,
            QM.photos, QM.startingPrice, QM.description, QM.status, QM.merchantAddress, QM.notice, qSysUser.loginCode))
            .from(QM)
            .leftJoin(qSysUser).on(QM.merchantCode.eq(qSysUser.userCode))
            .where(booleanBuilder)
            .orderBy(QM.merchantName.asc())
            .limit(pageable.getPageSize())
            .offset(pageable.getOffset());
        Page<MerchantsDTO> page = new PageImpl<>(jpaQuery.fetch(), pageable, jpaQuery.fetchCount());
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);

        return ResponseEntity.ok().headers(headers).body(page);
    }

    @PostMapping(value = "/merchants/pictureUpload")
    @ApiOperation(value = "图片上传")
    public ResponseEntity<String> pictureUpload(@RequestParam MultipartFile multipartFile) {
        if (multipartFile == null) {
            throw new CommonException("文件为空");
        }
        String fileName = multipartFile.getOriginalFilename();
        if (StringUtils.isEmpty(fileName)) {
            throw new CommonException("文件获取失败");
        }
        String fileSuffixName = fileName.substring(fileName.lastIndexOf("."));
        List<String> pictureFormatList = Arrays.asList(".jpg", ".jpeg", ".png", ".gif");
        if (!pictureFormatList.contains(fileSuffixName)) {
            throw new CommonException("请选择正确的图片");
        }
        fileName = Arrays.stream(LocalDateTime.now().toString().split("")).filter(s -> Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9").contains(s)).collect(Collectors.joining()) + fileSuffixName;
        //文件存储目录
        String filePath = applicationProperties.getFilePath();
        File file = new File(filePath + fileName);
        //若没有该目录则创建目录
        if (!file.getParentFile().exists()) {
            boolean bool = file.getParentFile().mkdirs();
            if (!bool) {
                throw new CommonException("目录创建失败");
            }
        }
        try {
            multipartFile.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok(filePath + fileName);
    }


    @GetMapping("/merchants/list/NoPaging")
    @ApiOperation(value = "商家列表下拉框-web", notes = "临时")
    public ResponseEntity<List<Merchant>> getMerchantList(@RequestParam(required = false) String merchantName,
                                                          @RequestParam(required = false) String status,
                                                          @ApiIgnore @CurrentUser UserModel userModel) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QM.status.eq("正常"));
        if (StringUtils.isNotEmpty(merchantName)) {
            booleanBuilder.and(QM.merchantName.contains(merchantName));
        }
        List<Merchant> result = queryFactory.selectFrom(QM)
            .where(booleanBuilder)
            .fetch();

        return ResponseEntity.ok(result);
    }


    @GetMapping("/getMerchantDetail")
    @ApiOperation(value = "查询商家个人信息", notes = "使用场景：app")
    public ResponseEntity<com.ruowei.modules.foodOrder.web.dto.MerchantDTO> getMerchantDetail(@ApiIgnore @CurrentUser UserModel userModel) {
        Optional<Merchant> opt = merchantRepository.findByMerchantCode(userModel.getUserCode());
        if (!opt.isPresent()) {
            throw new CommonException("个人信息异常");
        }
        com.ruowei.modules.foodOrder.web.dto.MerchantDTO merchantDTO = new com.ruowei.modules.foodOrder.web.dto.MerchantDTO();
        merchantDTO.setMerchantAddress(opt.get().getMerchantAddress());
        merchantDTO.setMerchantCode(opt.get().getMerchantCode());
        merchantDTO.setMerchantName(opt.get().getMerchantName());
        merchantDTO.setOpenTime(opt.get().getOpenTime());
        merchantDTO.setPhone(opt.get().getPhone());
        merchantDTO.setPhotos(opt.get().getPhotos());
        merchantDTO.setStatus(opt.get().getStatus());

        return ResponseEntity.ok(merchantDTO);
    }


    @PostMapping("/updateMerchantStatus")
    @ApiOperation(value = "设置商家店铺营业或歇业", notes = "使用场景：app")
    public ResponseEntity<com.ruowei.modules.foodOrder.web.dto.MerchantDTO> updateMerchantStatus(@RequestParam String status,
                                                                                                 @ApiIgnore @CurrentUser UserModel userModel) {
        Optional<Merchant> opt = merchantRepository.findByMerchantCode(userModel.getUserCode());
        if (!opt.isPresent()) {
            throw new CommonException("个人信息异常");
        }
        opt.get().setStatus(status);
        merchantRepository.saveAndFlush(opt.get());
        com.ruowei.modules.foodOrder.web.dto.MerchantDTO merchantDTO = new com.ruowei.modules.foodOrder.web.dto.MerchantDTO();
        merchantDTO.setMerchantAddress(opt.get().getMerchantAddress());
        merchantDTO.setMerchantCode(opt.get().getMerchantCode());
        merchantDTO.setMerchantName(opt.get().getMerchantName());
        merchantDTO.setOpenTime(opt.get().getOpenTime());
        merchantDTO.setPhone(opt.get().getPhone());
        merchantDTO.setPhotos(opt.get().getPhotos());
        merchantDTO.setStatus(status);

        return ResponseEntity.ok(merchantDTO);
    }


    @GetMapping("/getOrderList")
    @ApiOperation(value = "查询订单列表", notes = "使用场景：app")
    public ResponseEntity<Page<OrderWebDTO>> getOrderList(@RequestParam(required = false) String status,
                                                          @ApiIgnore @CurrentUser UserModel userModel,
                                                          Pageable pageable) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qOrder.deleteStatus.eq(false));
        booleanBuilder.and(qOrder.merchantCode.eq(userModel.getUserCode()));

        if (StringUtils.isNotEmpty(status)) {
            switch (status) {
                case "新订单": {
                    booleanBuilder.and(qOrder.status.in(OrderStatus.TO_BE_RECEIVED));
                    break;
                }
                case "退款中": {
                    booleanBuilder.and(qOrder.status.eq(OrderStatus.REFUND_APPLYING));
                    break;
                }
                case "进行中": {
                    booleanBuilder.and(qOrder.status.in(OrderStatus.MERCHANT_RECEIVED, OrderStatus.COURIER_RECEIVED));
                    break;
                }
                case "已完成": {
                    booleanBuilder.and(qOrder.status.in(OrderStatus.DELIVERED));
                    break;
                }
                case "已取消": {
                    booleanBuilder.and(qOrder.status.in(OrderStatus.CANCELLED, OrderStatus.MERCHANT_REFUSE_TO_RECEIVE, OrderStatus.REFUNDED));
                    break;
                }
            }
        }
        List<OrderWebDTO> list = new ArrayList<>(queryFactory.select(qOrder, qOrderItem)
            .from(qOrder)
            .leftJoin(qOrderItem).on(qOrder.orderCode.eq(qOrderItem.orderCode))
            .where(booleanBuilder)
            .orderBy(qOrder.confirmStatus.asc())
            .orderBy(qOrder.createTime.desc())
            .orderBy(qOrderItem.id.asc())
            .limit(pageable.getPageSize())
            .offset(pageable.getOffset())
            .transform(GroupBy.groupBy(qOrder).as(Projections.bean(OrderWebDTO.class, qOrder.orderCode, qOrder.createTime, qOrder.totalAmount, qOrder.payAmount,
                qOrder.receiverName, qOrder.receiverPhone, qOrder.receiverAddress, qOrder.remark, qOrder.status, qOrder.courierCode, qOrder.courierName, qOrder.courierPhone,
                GroupBy.list(Projections.bean(OrderItemWebDTO.class, qOrderItem.merchandiseName, qOrderItem.unitPrice, qOrderItem.quantity, qOrderItem.photos, qOrderItem.specification)).as("items"))))
            .values());
        List<OrderWebDTO> result = list.stream().peek(orderWebDTO ->
            refundApplicationRepository.findFirstByOrderCodeOrderByTimeDesc(orderWebDTO.getOrderCode())
                .ifPresent(refundApplication -> orderWebDTO.setReason(refundApplication.getReason())))
            .collect(Collectors.toList());
        long count = queryFactory.selectFrom(qOrder)
            .where(booleanBuilder).fetchCount();

        Page<OrderWebDTO> page = new PageImpl<>(result, pageable, count);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);

        return ResponseEntity.ok().headers(headers).body(page);
    }

    @PostMapping("/receivingOrder")
    @ApiOperation(value = "商家接单/拒绝接单", notes = "使用场景：app")
    @OrderLock
    public ResponseEntity<HashMap<String, String>> receivingOrder(@RequestBody ReceivingOrderDTO dto,
                                                                  @ApiIgnore @CurrentUser UserModel userModel) {
        Optional<Merchant> opt = merchantRepository.findOneByMerchantCode(userModel.getUserCode());
        if (!opt.isPresent()) {
            throw new CommonException("商家信息异常，登录失败");
        }
        Merchant merchant = opt.get();
        Optional<Order> orderOpt = orderRepository.findByOrderCode(dto.getOrderCode());
        if (!orderOpt.isPresent()) {
            throw new CommonException("所选订单已被处理");
        }

        Order order = orderOpt.get();
        if (!order.getStatus().equals(OrderStatus.TO_BE_RECEIVED)) {
            throw new CommonException("所选订单已被处理");
        }

        String title = "您的订单已被处理";
        String content;
        Map<String, String> map = new HashMap<>();
        map.put("id", String.valueOf(order.getId()));
        map.put("orderCode", order.getOrderCode());
        if (("同意").equals(dto.getIsReceivingOrder())) {
            order.setStatus(OrderStatus.MERCHANT_RECEIVED);
            content = "您的订单已接单";
            order.setMerchantReceiveTime(Instant.now());
            List<String> couriers = queryFactory.select(qCouriers.courierCode)
                .from(qCouriers)
                .where(qCouriers.availableStatus.eq(true)
                    .and(qCouriers.onLineStatus.eq(true)))
                .fetch();

            lifeCycleService.saveLifeCycle(order.getOrderCode(), null, "商家已接单", "商家已接单");

            for (String courier : couriers) {
                //给所有在线的状态正常的配送员发推送
                messagePushService.pushMessage(SenderType.SYSTEM, userModel.getUserCode(), courier, MessageType.FOOD_ORDER,
                    true, "抢单通知", "发现新订单，快来抢单吧", map, ReceiverType.COURIER_APP);
            }
        } else {
            order.setStatus(OrderStatus.MERCHANT_REFUSE_TO_RECEIVE);
            content = "您的订单被拒绝";

            lifeCycleService.saveLifeCycle(order.getOrderCode(), null, "商家拒绝接单", "商家拒绝接单");
            lifeCycleService.saveLifeCycle(order.getOrderCode(), null, "退款中", "退款中");

            refund(order, dto.getOrderCode());
        }
        order.setDeliveryTime(Instant.now());
        order.setUpdateTime(Instant.now());
        orderRepository.saveAndFlush(order);
        //推送
        map.put("status", order.getStatus().getMessage());
        messagePushService.pushMessage(SenderType.SYSTEM, userModel.getUserCode(), order.getMemberCode(), MessageType.FOOD_ORDER,
            true, "商家接单通知", content, map, ReceiverType.APPLET);

        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("code", "200");
        if (("同意").equals(dto.getIsReceivingOrder())) {
            hashMap.put("msg", "同意接单");
        } else {
            hashMap.put("msg", "拒绝接单");
        }
        return ResponseEntity.ok(hashMap);
    }


    @PostMapping("/disposeRefund")
    @ApiOperation(value = "商家处理退款申请")
    @OrderLock
    public ResponseEntity<HashMap<String, String>> disposeRefund(@RequestBody RefundDTO dto,
                                                                 @ApiIgnore @CurrentUser UserModel userModel) {

        Optional<Order> orderOpt = orderRepository.findByOrderCode(dto.getOrderCode());
        if (!orderOpt.isPresent()) {
            throw new CommonException("所选订单已被处理");
        }
        Optional<RefundApplication> opt = refundApplicationRepository.findFirstByOrderCodeOrderByTimeDesc(orderOpt.get().getOrderCode());
        if (!opt.isPresent()) {
            throw new CommonException("退款申请已被处理");
        }
        RefundApplication refundApplication = opt.get();
        if (refundApplication.getHandleTime() != null) {
            throw new CommonException("退款申请已被处理");
        }
        log.info("商家处理退款");
        String title;
        String content;
        Order order = orderOpt.get();
        Merchant merchant = merchantRepository.findByMerchantCode(order.getMerchantCode()).orElseThrow(() -> new CommonException("商家不存在"));
        if (!order.getStatus().equals(OrderStatus.REFUND_APPLYING)) {
            throw new CommonException("所选订单已被处理");
        }
        if (("同意").equals(dto.getIsAgree())) {
            //退款
            refund(order, dto.getOrderCode());

            order.setStatus(OrderStatus.REFUND_AGREE);
            order.setUpdateTime(Instant.now());
            content = "您发起的退款申请已通过";
            lifeCycleService.saveLifeCycle(order.getOrderCode(), refundApplication.getApplicationCode(), "商家同意退款", "商家已同意您的退款申请");
            lifeCycleService.saveLifeCycle(order.getOrderCode(), refundApplication.getApplicationCode(), "退款中", "退款中");
        } else {
            if (StringUtils.isNotEmpty(order.getCourierCode())) {
                order.setStatus(OrderStatus.COURIER_RECEIVED);
            } else {
                order.setStatus(OrderStatus.MERCHANT_RECEIVED);
            }
            order.setUpdateTime(Instant.now());
            content = "您发起的退款申请已被拒绝";
            lifeCycleService.saveLifeCycle(order.getOrderCode(), refundApplication.getApplicationCode(), "商家拒绝退款", "您的退款申请已被拒绝，如有疑问，请联系店家");
        }
        orderRepository.saveAndFlush(order);

        if (("同意").equals(dto.getIsAgree())) {
            refundApplication.setStatus(OrderStatus.REFUND_AGREE);
        } else {
            refundApplication.setStatus(OrderStatus.REFUND_REFUSE);
        }
        refundApplication.setHandleTime(Instant.now());
        Optional<SysUserTable> userOpt = sysUserRepository.findOneByUserCode(userModel.getUserCode());
        if (!userOpt.isPresent()) {
            throw new CommonException("当前账户异常");
        }
        refundApplication.setHandler(userOpt.get().getUserName());//处理人
        refundApplicationRepository.save(refundApplication);

        Map<String, String> customMessage = new HashMap<>();
        customMessage.put("id", String.valueOf(order.getId()));
        customMessage.put("orderCode", order.getOrderCode());
        customMessage.put("status", order.getStatus().getMessage());
        customMessage.put("refundId", String.valueOf(opt.get().getId()));
        if (("同意").equals(dto.getIsAgree())) {
            title = "商家同意退款";
            if (order.getStatus().equals(OrderStatus.COURIER_RECEIVED) && StringUtils.isNotEmpty(order.getCourierCode())) {
                //推送给配送员
                messagePushService.pushMessage(SenderType.SYSTEM, userModel.getUserCode(), order.getCourierCode(), MessageType.FOOD_ORDER,
                    true, "订单取消", "客户已取消订单，请及时查看", customMessage, ReceiverType.COURIER_APP);
            }
        } else {
            title = "商家拒绝退款";
            if (order.getStatus().equals(OrderStatus.COURIER_RECEIVED) && StringUtils.isNotEmpty(order.getCourierCode())) {
                //推送给配送员
                messagePushService.pushMessage(SenderType.SYSTEM, userModel.getUserCode(), order.getCourierCode(), MessageType.FOOD_ORDER,
                    true, "订单更新", "有订单更新，请及时查看", customMessage, ReceiverType.COURIER_APP);
            } else if (order.getStatus().equals(OrderStatus.MERCHANT_RECEIVED)) {
                //给所有在线的状态正常的配送员发推送
                Map<String, String> map = new HashMap<>();
                map.put("id", String.valueOf(order.getId()));
                map.put("orderCode", order.getOrderCode());
                List<String> couriers = queryFactory.select(qCouriers.courierCode)
                    .from(qCouriers)
                    .where(qCouriers.availableStatus.eq(true)
                        .and(qCouriers.onLineStatus.eq(true)))
                    .fetch();
                for (String courier : couriers) {
                    messagePushService.pushMessage(SenderType.SYSTEM, userModel.getUserCode(), courier, MessageType.FOOD_ORDER,
                        true, "抢单通知", "发现新订单，快来抢单吧", map, ReceiverType.COURIER_APP);
                }
            }
        }
        //推送给用户
        messagePushService.pushMessage(SenderType.SYSTEM, userModel.getUserCode(), order.getMemberCode(), MessageType.FOOD_ORDER,
            true, title, content, customMessage, ReceiverType.APPLET);

        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("code", "200");
        if (("同意").equals(dto.getIsAgree())) {
            hashMap.put("msg", "同意退款");
        } else {
            hashMap.put("msg", "拒绝退款");
        }
        return ResponseEntity.ok(hashMap);
    }

    private void refund(Order order, String orderCode) {
        Map<String, String> result;
        try {
            result = weChatPayService.refund(order.getPayAmount(), order.getOrderCode());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("退款失败，{},{}", e.getMessage(), e.toString());
            payReturnService.saveFailedRecord(orderCode, null, order.getPayAmount(), null,
                null, null, e.getMessage(), null, null);
            throw new CommonException("退款失败，请重试");
        }
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(result.get("return_msg")) && !result.get("return_msg").equals("OK")) {

            payReturnService.saveFailedRecord(orderCode,
                result.get("out_refund_no"),
                order.getPayAmount(),
                result.get("return_msg"),
                result.get("result_code"),
                result.get("err_code"),
                result.get("err_code_des"),
                result.get("transaction_id"),
                result.get("refund_id"));

            throw new CommonException(result.get("return_msg"));
        }
        if (!result.get("return_code").equals("SUCCESS") || !result.get("result_code").equals("SUCCESS")) {
            log.error("退款失败，{}", result.toString());

            payReturnService.saveFailedRecord(orderCode,
                result.get("out_refund_no"),
                order.getPayAmount(),
                result.get("return_msg"),
                result.get("result_code"),
                result.get("err_code"),
                result.get("err_code_des"),
                result.get("transaction_id"),
                result.get("refund_id"));

            throw new CommonException("退款失败:" + result.get("err_code_des"));
        }
    }
}
